---
title: Username
description: Username plugin
---

The username plugin is a lightweight plugin that adds username support to the email and password authenticator. This allows users to sign in and sign up with their username instead of their email.

## Installation

<Steps>
    <Step>
        ### Add Plugin to the server

        ```ts title="auth.ts"
        import { betterAuth } from "better-auth"
        import { username } from "better-auth/plugins"

        export const auth = betterAuth({
            emailAndPassword: { // [!code highlight]
                enabled: true, // [!code highlight]
            }, // [!code highlight]
            plugins: [ // [!code highlight]
                username() // [!code highlight]
            ] // [!code highlight]
        })
        ```
    </Step>
    <Step>
        ### Migrate the database

        Run the migration or generate the schema to add the necessary fields and tables to the database.

        <Tabs items={["migrate", "generate"]}>
            <Tab value="migrate">
            ```bash
            npx @better-auth/cli migrate
            ```
            </Tab>
            <Tab value="generate">
            ```bash
            npx @better-auth/cli generate
            ```
            </Tab>
        </Tabs>
        See the [Schema](#schema) section to add the fields manually.
    </Step>
    <Step>
        ### Add the client plugin

        ```ts title="auth-client.ts"
        import { createAuthClient } from "better-auth/client"
        import { usernameClient } from "better-auth/client/plugins"

        export const authClient = createAuthClient({
            plugins: [ // [!code highlight]
                usernameClient() // [!code highlight]
            ] // [!code highlight]
        })
        ```
    </Step>
</Steps>

## Usage

### Sign up

To sign up a user with username, you can use the existing `signUp.email` function provided by the client.
The `signUp` function should take a new `username` property in the object.

<APIMethod path="/sign-up/email" method="POST">
```ts
type signUpEmail = {
    /**
     * The email of the user.
    */
    email: string = "email@domain.com"
    /**
     * The name of the user.
    */
    name: string = "Test User"
    /**
     * The password of the user.
    */
    password: string = "password1234"
    /**
     * The username of the user.
    */
    username: string = "test"
    /**
     * An optional display username of the user.
    */
    displayUsername?: string = "Test User123"
}
```
</APIMethod>


<Callout type="info">
    If only `username` is provided, the `displayUsername` will be set to the pre normalized version of the `username`. You can see the [Username Normalization](#username-normalization) and [Display Username Normalization](#display-username-normalization) sections for more details.
</Callout>

### Sign in

To sign in a user with username, you can use the `signIn.username` function provided by the client.

<APIMethod path="/sign-in/username" method="POST">
```ts
type signInUsername = {
    /**
     * The username of the user.
    */
    username: string = "test"
    /**
     * The password of the user.
    */
    password: string = "password1234"
}
```
</APIMethod>

### Update username

To update the username of a user, you can use the `updateUser` function provided by the client.

<APIMethod path="/update-user" method="POST">
```ts
type updateUser = {
    /**
     * The username to update.
    */
    username?: string = "new-username"
}
```
</APIMethod>

### Check if username is available

To check if a username is available, you can use the `isUsernameAvailable` function provided by the client.

<APIMethod path="/is-username-available" method="POST" resultVariable="response">
```ts
type isUsernameAvailable = {
    /**
     * The username to check.
    */
    username: string = "new-username"
}

if(response?.available) {
    console.log("Username is available");
} else {
    console.log("Username is not available");
}
```
</APIMethod>

## Options

### Min Username Length

The minimum length of the username. Default is `3`.

```ts title="auth.ts"
import { betterAuth } from "better-auth"
import { username } from "better-auth/plugins"

const auth = betterAuth({
    emailAndPassword: {
        enabled: true,
    },
    plugins: [
        username({
            minUsernameLength: 5
        })
    ]
})
```

### Max Username Length

The maximum length of the username. Default is `30`.

```ts title="auth.ts"
import { betterAuth } from "better-auth"
import { username } from "better-auth/plugins"

const auth = betterAuth({
    emailAndPassword: {
        enabled: true,
    },
    plugins: [
        username({
            maxUsernameLength: 100
        })
    ]
})
```

### Username Validator

A function that validates the username. The function should return false if the username is invalid. By default, the username should only contain alphanumeric characters, underscores, and dots.

```ts title="auth.ts"
import { betterAuth } from "better-auth"
import { username } from "better-auth/plugins"

const auth = betterAuth({
    emailAndPassword: {
        enabled: true,
    },
    plugins: [
        username({
            usernameValidator: (username) => {
                if (username === "admin") {
                    return false
                }
                return true
            }
        })
    ]
})
```

### Display Username Validator

A function that validates the display username. The function should return false if the display username is invalid. By default, no validation is applied to display username.

```ts title="auth.ts"
import { betterAuth } from "better-auth"
import { username } from "better-auth/plugins"

const auth = betterAuth({
    emailAndPassword: {
        enabled: true,
    },
    plugins: [
        username({
            displayUsernameValidator: (displayUsername) => {
                // Allow only alphanumeric characters, underscores, and hyphens
                return /^[a-zA-Z0-9_-]+$/.test(displayUsername)
            }
        })
    ]
})
```

### Username Normalization

A function that normalizes the username, or `false` if you want to disable normalization.

By default, usernames are normalized to lowercase, so "TestUser" and "testuser", for example, are considered the same username. The `username` field will contain the normalized (lower case) username, while `displayUsername` will contain the original `username`.

```ts title="auth.ts"
import { betterAuth } from "better-auth"
import { username } from "better-auth/plugins"

const auth = betterAuth({
    emailAndPassword: {
        enabled: true,
    },
    plugins: [
        username({
            usernameNormalization: (username) => {
                return username.toLowerCase()
                    .replaceAll("0", "o")
                    .replaceAll("3", "e")
                    .replaceAll("4", "a");
            }
        })
    ]
})
```

### Display Username Normalization

A function that normalizes the display username, or `false` to disable normalization.

By default, display usernames are not normalized. When only `username` is provided during signup or update, the `displayUsername` will be set to match the original `username` value (before normalization). You can also explicitly set a `displayUsername` which will be preserved as-is. For custom normalization, provide a function that takes the display username as input and returns the normalized version.

```ts title="auth.ts"
import { betterAuth } from "better-auth"
import { username } from "better-auth/plugins"

const auth = betterAuth({
    emailAndPassword: {
        enabled: true,
    },
    plugins: [
        username({
            displayUsernameNormalization: (displayUsername) => displayUsername.toLowerCase(),
        })
    ]
})
```

### Validation Order

By default, username and display username are validated before normalization. You can change this behavior by setting `validationOrder` to `post-normalization`.

```ts title="auth.ts"
import { betterAuth } from "better-auth"
import { username } from "better-auth/plugins"

const auth = betterAuth({
    emailAndPassword: {
        enabled: true,
    },
    plugins: [
        username({
            validationOrder: {
                username: "post-normalization",
                displayUsername: "post-normalization",
            }
        })
    ]
})
```

## Schema

The plugin requires 2 fields to be added to the user table:

<DatabaseTable
    fields={[
        {
            name: "username",
            type: "string",
            description: "The username of the user",
            isUnique: true
        },
        {
            name: "displayUsername",
            type: "string",
            description: "Non normalized username of the user",
            isUnique: true
        },
    ]}
/>
